package com.ruoyi.system.service.impl;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.AliYunSmsConstants;
import com.ruoyi.common.constant.LianLuSmsConstants;
import com.ruoyi.common.constant.SysConfigConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.entity.BO.SmsSendBO;
import com.ruoyi.common.entity.DO.AppletTemplateDO;
import com.ruoyi.common.entity.DO.AppletTemplateLogDO;
import com.ruoyi.common.entity.DO.shop.ShopAppletDO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.AliYunSmsUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.lianlu.LianluSmsUtils;
import com.ruoyi.system.mapper.IBackAppletTemplateLogMapper;
import com.ruoyi.system.mapper.IBackAppletTemplateMapper;
import com.ruoyi.system.mapper.IBackShopConfigMapper;
import com.ruoyi.system.service.IAsyncNotifyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;

@Service("AsyncNotifyServiceImpl")
@Slf4j
public class AsyncNotifyServiceImpl implements IAsyncNotifyService {

    @Value("${applet.miniprogram_state}")
    private String miniprogramState;

    @Value("${applet.lang}")
    private String lang;

    @Value("${applet.accessTokenUrl}")
    private String accessTokenUrl;

    @Value("${applet.templateUrl}")
    private String appletTemplateUrl;

    @Resource
    private IBackAppletTemplateLogMapper appletTemplateLogMapper;

    @Resource
    private IBackAppletTemplateMapper appletTemplateMapper;

    @Resource
    private IBackShopConfigMapper shopConfigMapper;

    @Resource
    private AliYunSmsUtils aliYunSmsUtils;

    public void sendWechatTemplateNotify(HashMap<String, String> params) {
        Long shopId = Long.valueOf(params.get("shopId"));
        String configVal = shopConfigMapper.searchValueByKey(SysConfigConstants.ShopConfigEnum.WXNOTIFY_SWITCH.getKey(), shopId);
        if (!UserConstants.YES.equals(configVal)) {
            return;
        }
        configVal = shopConfigMapper.searchValueByKey("wxnotify." + params.get("templateKey"), shopId);
        if (!UserConstants.YES.equals(configVal)) {
            return;
        }
        String templateId = selectTemplateIdByKey(params.get("templateKey"));
        if (StringUtils.isEmpty(templateId)) {
            log.error("无效模板键值，KEY：" + params.get("templateKey"));
        }
        JSONObject queueObj = new JSONObject();
        queueObj.put("touser", params.get("openid"));
        queueObj.put("template_id", templateId);
        queueObj.put("miniprogram_state", miniprogramState);
        queueObj.put("lang", lang);
        switch (params.get("templateKey")) {
            case "recharge":
                queueObj.put("page", "pages/mine/consumption-history/index");
                queueObj.put("data", getRechargeSuccessNotifyTemplateData(params));
                break;
            case "balanceChange":
                queueObj.put("page", "pages/mine/consumption-history/index");
                queueObj.put("data", getBalanceChangeNotifyTemplateData(params));
                break;
            case "couponReceive":
                queueObj.put("page", "pages/mine/discount-card/index");
                queueObj.put("data", getCouponReceiveTemplateData(params));
                break;
            case "couponExpire":
                queueObj.put("page", "pages/mine/discount-card/index");
                queueObj.put("data", getCouponRemindTemplateData(params));
                break;
            default:
                log.error("无处理，KEY：" + params.get("templateKey"));
                break;
        }
        AppletTemplateLogDO appletTemplateLogDO = new AppletTemplateLogDO();
        appletTemplateLogDO.setTouser(queueObj.get("touser").toString());
        appletTemplateLogDO.setTemplateId(queueObj.get("template_id").toString());
        appletTemplateLogDO.setPage(queueObj.get("page").toString());
        appletTemplateLogDO.setMiniprogramState(queueObj.get("miniprogram_state").toString());
        appletTemplateLogDO.setLang(queueObj.get("lang").toString());
        appletTemplateLogDO.setData(queueObj.get("data").toString());
        appletTemplateLogDO.setCreateTime(new Date());
//        log.info("请求数据:" + queueObj.toString());
        doSendWechatTemplateNotify(Long.valueOf(params.get("shopId")), queueObj.toString());
        appletTemplateLogMapper.insertSelective(appletTemplateLogDO);
    }

    @Override
    public void sendSmsNotify(HashMap<String, String> params) {
        Long shopId = Long.valueOf(params.get("shopId"));
        String configVal = shopConfigMapper.searchValueByKey(SysConfigConstants.ShopConfigEnum.SMSNOTIFY_SWITCH.getKey(), shopId);
        if (!UserConstants.YES.equals(configVal)) {
            return;
        }
        configVal = shopConfigMapper.searchValueByKey("smsnotify." + params.get("templateKey"), shopId);
        if (!UserConstants.YES.equals(configVal)) {
            return;
        }
        HashMap<String, String> smsParam = new HashMap<>();
        if (params.containsKey("smsCompany") && String.valueOf(params.get("smsCompany")).equals("aliyun")) {
            if (params.containsKey("templateCode")) {
                smsParam.put("code", params.get("templateCode"));
            } else {
                smsParam.put("code", AliYunSmsConstants.TemplateEnum.match(params.get("templateKey")).getAliCode());
            }
            smsParam.put("signName", AliYunSmsConstants.SignEnum.match(shopId));
            smsParam.put("phone", params.get("phone"));
            log.info("请求数据:" + JSONObject.toJSONString(smsParam));
            try {
                aliYunSmsUtils.send(smsParam);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("发送阿里云短信失败！:" + JSONObject.toJSONString(smsParam));
            }
        } else {
            //获取短信内容 替换短信变量
            LianLuSmsConstants.TemplateEnum templateEnum = LianLuSmsConstants.TemplateEnum.match(params.get("templateKey"));
            SmsSendBO smsSendBO = new SmsSendBO();
            smsSendBO.setNotify(true);
            smsSendBO.setPhoneNumberArr(new String[]{params.get("phone")});
            smsSendBO.setTemplateCode(templateEnum.getTemplateId());
            smsSendBO.setTemplateParamArr(params.get("smsVar").split(","));
            log.info("请求数据:" + JSONObject.toJSONString(smsParam));
            try {
                LianluSmsUtils.templateSend(smsSendBO);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("发送联麓短信失败！:" + JSONObject.toJSONString(smsSendBO));
            }
        }
    }

    private void doSendWechatTemplateNotify(Long shopId, String queueJsonStr) {
        //TODO：查询店铺的appId和secret
        ShopAppletDO shopApplet = appletTemplateMapper.getShopAppletInfo(shopId);
        if (shopApplet == null) {
            throw new BusinessException("请联系运营平台重新开通小程序！");
        }
        RestTemplate restTemplate = new RestTemplate();
        String resultStr = restTemplate.getForObject(accessTokenUrl, String.class, shopApplet.getAppletAppId(), shopApplet.getAppletSecret(), "client_credential");
        if (StringUtils.isEmpty(resultStr)) {
            throw new BusinessException("网络异常，请稍后再试！");
        }
        try {
            JSONObject resultObj = JSONObject.parseObject(resultStr);
            if (resultObj.containsKey("errcode") && resultObj.getIntValue("errcode") != 0) {
                throw new BusinessException("网络异常，请稍后再试！");
            }
            String accessToken = resultObj.getString("access_token");
            HttpHeaders headers = new HttpHeaders();
            headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            HttpEntity<String> formEntity = new HttpEntity<String>(queueJsonStr, headers);
            resultStr = restTemplate.postForEntity(appletTemplateUrl + accessToken, formEntity, String.class).getBody();
            if (StringUtils.isEmpty(resultStr)) {
                throw new BusinessException("网络异常，请稍后再试！");
            }
            resultObj = JSONObject.parseObject(resultStr);
            if (resultObj.containsKey("errcode") && resultObj.getIntValue("errcode") != 0) {
                log.error(resultObj.getString("errcode") + ":" + resultObj.getString("errmsg"));
            }
        } catch (JSONException e) {
//            e.printStackTrace();
            throw new BusinessException("访问小程序服务器超时，请稍后再试！");
        }
    }

    private JSONObject getCouponReceiveTemplateData(HashMap<String, String> params) {
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("title"));
        jsonObject.put("thing1", jsonObjectTmp); //优惠券名称

        jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("discountValueDesc"));
        jsonObject.put("amount2", jsonObjectTmp); //面值

        jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("useEndTime"));
        jsonObject.put("time3", jsonObjectTmp); //到期时间

        jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("remark"));
        jsonObject.put("thing5", jsonObjectTmp);//温馨提示（）

        return jsonObject;
    }

    private JSONObject getCouponRemindTemplateData(HashMap<String, String> params) {
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("title"));
        jsonObject.put("thing2", jsonObjectTmp); //优惠券名称

        jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("discountValueDesc"));
        jsonObject.put("amount5", jsonObjectTmp); //优惠额度

        jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("useEndTime"));
        jsonObject.put("date4", jsonObjectTmp); //到期时间

        jsonObjectTmp = new JSONObject();
        jsonObjectTmp.put("value", params.get("remark"));
        jsonObject.put("thing1", jsonObjectTmp);//温馨提示（备注用来显示赠送多少积分，总积分多少）

        return jsonObject;
    }

    public com.ruoyi.common.json.JSONObject getRechargeSuccessNotifyTemplateData(HashMap<String, String> params) {
        com.ruoyi.common.json.JSONObject jsonObject = new com.ruoyi.common.json.JSONObject();
        String thing1 = "";
        String amount3 = "";
        String time2 = "";
        String character_string7 = "";
        String thing13 = "如对订单有疑问，请联系商家确认";
        if ("Y".equals(params.get("isInfo"))) {
            thing1 = params.get("orderStatusDesc");
            amount3 = params.get("amount");
            time2 = params.get("payTime");
            character_string7 = params.get("orderSn");
            if (params.containsKey("creditRemark")) {
                thing13 = params.get("creditRemark");
            }
        }
        com.ruoyi.common.json.JSONObject jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", thing1);
        jsonObject.put("thing1", jsonObjectTmp); //充值状态

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", amount3);
        jsonObject.put("amount3", jsonObjectTmp); //充值金额

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", time2);
        jsonObject.put("time2", jsonObjectTmp); //充值时间

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", character_string7);
        jsonObject.put("character_string7", jsonObjectTmp); //订单编号

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", thing13);
        jsonObject.put("thing13", jsonObjectTmp);//备注（备注用来显示赠送多少积分，总积分多少）

        return jsonObject;
    }

    public com.ruoyi.common.json.JSONObject getBalanceChangeNotifyTemplateData(HashMap<String, String> params) {
        com.ruoyi.common.json.JSONObject jsonObject = new com.ruoyi.common.json.JSONObject();
        String thing5; //变动类型
        String character_string2;//变动金额
        String time1; //变动时间
        String amount3; //当前余额
        String thing4 = "如对余额变动有疑问，请联系商家确认";//备注
        thing5 = params.get("linkModelDesc");
        character_string2 = params.get("changeBalance");
        time1 = params.get("createTime");
        amount3 = params.get("newBalance");

        com.ruoyi.common.json.JSONObject jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", thing5);
        jsonObject.put("thing5", jsonObjectTmp);  //变动类型

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", character_string2);
        jsonObject.put("character_string2", jsonObjectTmp); //变动金额

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", amount3);
        jsonObject.put("amount3", jsonObjectTmp); //当前余额

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", time1);
        jsonObject.put("time1", jsonObjectTmp); //充值时间

        jsonObjectTmp = new com.ruoyi.common.json.JSONObject();
        jsonObjectTmp.put("value", thing4);
        jsonObject.put("thing4", jsonObjectTmp); //备注
        return jsonObject;
    }

    private String selectTemplateIdByKey(String templateKey) {
        Example example = new Example(AppletTemplateDO.class);
        example.createCriteria().andEqualTo("templateKey", templateKey);
        AppletTemplateDO appletTemplate = appletTemplateMapper.selectOneByExample(example);
        return StringUtils.isNotNull(appletTemplate) ? appletTemplate.getTemplateId() : "";
    }
}
